﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace isDrone
{
   public class Input
   {
       private bool _enabled = false;
       public bool Enabled { get { return _enabled; } }
       private SharpDX.DirectInput.DirectInput _directInput;
       private SharpDX.DirectInput.Joystick j;
       private System.Timers.Timer _timer;
       private System.Timers.Timer _timer2;
       private SharpDX.DirectInput.JoystickState _lastjstate;
       private InputState _laststate;
       private bool xbox = true;


       public Input()
       {   _timer = new System.Timers.Timer(30);
           _timer.Elapsed += timer;    
           _directInput = new SharpDX.DirectInput.DirectInput();
           init();

           _timer2 = new System.Timers.Timer(1000);
           _timer2.Elapsed += timer2;
           _timer2.Start();
       }

       private void timer2(object sender, EventArgs e)
       {
          
           if (!Enabled)
               init();
       }


       public void init()
       {
           var dev = _directInput.GetDevices(SharpDX.DirectInput.DeviceType.Gamepad, SharpDX.DirectInput.DeviceEnumerationFlags.AllDevices).ToList();
           int maxcount = 0;
           int index = -1;
           for (int i = 0; i < dev.Count; i++)
           {
               var d = dev[i];
               var t = new SharpDX.DirectInput.Joystick(_directInput, dev[i].InstanceGuid).Capabilities.AxeCount;
               if (t > maxcount)
               {
                   maxcount = t;
                   index =i;
               }
           }
       
           if (dev.Count > 0 )
             
           {

                j = new SharpDX.DirectInput.Joystick(_directInput, dev[index].InstanceGuid);
               j.Acquire();
               _timer.Start();
               _enabled = true;
               xbox = maxcount==5;

           }

     
       }

       private object lo = new object();
       private void timer(object sender, EventArgs e)
       {
           lock (lo)
           {
               try
               {
                   var s = j.GetCurrentState();
                   if (xbox)
                   {

                       if (_lastjstate != null)
                       {
                           if (!_lastjstate.Buttons[2] && s.Buttons[2])
                               if (FlatTrim != null) FlatTrim();

                           if (!_lastjstate.Buttons[0] && s.Buttons[0])
                               if (FullScrean != null) FullScrean();

                           if (!_lastjstate.Buttons[1] && s.Buttons[1])
                               if (Hover != null) Hover();
                           if (!_lastjstate.Buttons[4] && s.Buttons[4])
                               if (VideoStart != null) VideoStart();

                           if (!_lastjstate.Buttons[5] && s.Buttons[5])
                               if (VideoStop != null) VideoStop();
                           if (!_lastjstate.Buttons[7] && s.Buttons[7])
                               Start();
                           if (!_lastjstate.Buttons[6] && s.Buttons[6])
                               Stop();
                           if (!_lastjstate.Buttons[3] && s.Buttons[3])
                               Emergency();

                           if (_lastjstate.PointOfViewControllers[0] != 27000 && s.PointOfViewControllers[0] == 27000)
                               if (SetMin != null) SetMin();
                           if (_lastjstate.PointOfViewControllers[0] != 18000 && s.PointOfViewControllers[0] == 18000)
                               if (Mode != null) Mode();
                           if (_lastjstate.PointOfViewControllers[0] != 0 && s.PointOfViewControllers[0] == 0)
                               if (Magneto != null) Magneto();

                           if (_lastjstate.PointOfViewControllers[0] != 9000 && s.PointOfViewControllers[0] == 9000)
                               if (SetPlus != null) SetPlus();
                       }
                       _lastjstate = s;
                       InputState st = new InputState();
                       st.Emergency = s.Buttons[3];
                       st.Start = s.Buttons[7];
                       st.Stop = s.Buttons[6];
                       st.Tangag = (float) (-s.RotationY/Convert.ToDouble(UInt16.MaxValue)*2 + 1);
                       st.Tangag = Math.Abs(st.Tangag) > 0.05 ? st.Tangag : 0;
                       st.Kren = (float) (s.RotationX/Convert.ToDouble(UInt16.MaxValue)*2 - 1);
                       st.Kren = Math.Abs(st.Kren) > 0.05 ? st.Kren : 0;
                       st.Riskanie = (float) (s.X/Convert.ToDouble(UInt16.MaxValue)*2 - 1);
                       st.Riskanie = Math.Abs(st.Riskanie) > 0.05 ? st.Riskanie : 0;
                       st.Gaz = -(float) (s.Z/Convert.ToDouble(UInt16.MaxValue)*2 - 1);
                       st.Gaz = Math.Abs(st.Gaz) > 0.05 ? st.Gaz : 0;
                       if (_laststate != null)
                       {
                           if (_laststate.Compare(st))
                           {
                               Update(st);
                               _laststate = st;
                           }
                       }
                       else
                           _laststate = st;
                   }
                   else
                   {
                       if (_lastjstate != null)
                       {
                           if (!_lastjstate.Buttons[3] && s.Buttons[3])
                               if (FlatTrim != null) FlatTrim();

                           if (!_lastjstate.Buttons[0] && s.Buttons[0])
                               if (FullScrean != null) FullScrean();

                           if (!_lastjstate.Buttons[1] && s.Buttons[1])
                               if (Hover != null) Hover();
                           if (!_lastjstate.Buttons[6] && s.Buttons[6])
                               if (VideoStart != null) VideoStart();

                           if (!_lastjstate.Buttons[7] && s.Buttons[7])
                               if (VideoStop != null) VideoStop();
                           if (!_lastjstate.Buttons[11] && s.Buttons[11])
                               Start();
                           if (!_lastjstate.Buttons[10] && s.Buttons[10])
                               Stop();
                           if (!_lastjstate.Buttons[4] && s.Buttons[4])
                               Emergency();

                           if (_lastjstate.PointOfViewControllers[0] != 27000 && s.PointOfViewControllers[0] == 27000)
                               if (SetMin != null) SetMin();
                           if (_lastjstate.PointOfViewControllers[0] != 18000 && s.PointOfViewControllers[0] == 18000)
                               if (Mode != null) Mode();
                           if (_lastjstate.PointOfViewControllers[0] != 0 && s.PointOfViewControllers[0] == 0)
                               if (Magneto != null) Magneto();

                           if (_lastjstate.PointOfViewControllers[0] != 9000 && s.PointOfViewControllers[0] == 9000)
                               if (SetPlus != null) SetPlus();
                       }
                       _lastjstate = s;
                       InputState st = new InputState();
                       st.Emergency = s.Buttons[4];
                       st.Start = s.Buttons[11];
                       st.Stop = s.Buttons[10];
                       st.Tangag = (float)(-s.RotationZ / Convert.ToDouble(UInt16.MaxValue) * 2 + 1);
                       st.Tangag = Math.Abs(st.Tangag) > 0.05 ? st.Tangag : 0;
                       st.Kren = (float) (s.Z/Convert.ToDouble(UInt16.MaxValue)*2 - 1);
                       st.Kren = Math.Abs(st.Kren) > 0.05 ? st.Kren : 0;
                       st.Riskanie = (float) (s.X/Convert.ToDouble(UInt16.MaxValue)*2 - 1);
                       st.Riskanie = Math.Abs(st.Riskanie) > 0.05 ? st.Riskanie : 0;
                       if (_lastjstate.Buttons[9])
                           st.Gaz = 1;
                       if (_lastjstate.Buttons[8])
                           st.Gaz = -1;
                       if (_laststate != null)
                       {
                           if (_laststate.Compare(st))
                           {
                               Update(st);
                               _laststate = st;
                           }
                       }
                       else
                           _laststate = st;
                   }
               }
               catch
               {
                   _enabled = false;
                   _timer.Stop();
               }
           }

       }

       public void Start()
       {
           if (StartEvent == null) return;
           var t = new Thread(new ThreadStart(StartEvent));
           t.Start();
       }

       public void Stop()
       {
           if (StopEvent == null) return;
           var t = new Thread(new ThreadStart(StopEvent));
           t.Start();
       }

       public void Emergency()
       {
           if (EmergencyEvent == null) return;
           var t = new Thread(new ThreadStart(EmergencyEvent));
           t.Start();
       }

       public void Update(InputState state)
       {
           SharpDX.Windows.RenderControl c = new SharpDX.Windows.RenderControl();
      
           if (UpdatEvente == null) return;
           var t = new Thread(delegate(System.Object o)
           {
               UpdatEvente((InputState) o);
           });
           t.Start(state);

       }
       public event ButtonHandler Magneto;
       public event ButtonHandler Mode;
       public event ButtonHandler FullScrean;

       public event ButtonHandler VideoStart;
       public event ButtonHandler VideoStop;


       public event ButtonHandler SetPlus;
       public event ButtonHandler SetMin;

       public event ButtonHandler Hover;
       public event ButtonHandler FlatTrim;

    

       public event ButtonHandler StartEvent;
       public event ButtonHandler StopEvent;
       public event ButtonHandler EmergencyEvent;
       public event AxisHandler UpdatEvente;

       public delegate void ButtonHandler();
       public delegate void AxisHandler(InputState state);
      

    }
}
